"""
RJ45 Interface

实现基于TCP/IP的RJ45通信接口
"""

import socket
import threading
import time
from typing import Optional
from .base import RadarInterface
from ..exceptions import RadarConnectionError, RadarTimeoutError


class RJ45Interface(RadarInterface):
    """RJ45 TCP/IP通信接口"""

    def __init__(self, config: dict):
        super().__init__(config)
        self.host = config.get('ip_address', '192.168.1.100')
        self.data_port = config.get('data_port', 50001)
        self.control_port = config.get('control_port', 50002)
        self.data_socket: Optional[socket.socket] = None
        self.control_socket: Optional[socket.socket] = None
        self._receive_thread: Optional[threading.Thread] = None
        self._stop_receiving = False

    def connect(self) -> None:
        """连接到雷达设备"""
        try:
            # 创建数据端口socket
            self.data_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.data_socket.settimeout(self.timeout / 1000)
            self.data_socket.connect((self.host, self.data_port))

            # 创建控制端口socket
            self.control_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.control_socket.settimeout(self.timeout / 1000)
            self.control_socket.connect((self.host, self.control_port))

            self.is_connected = True
            self._start_receiving()

        except socket.error as e:
            self.disconnect()
            raise RadarConnectionError(f"连接到 {self.host}:{self.data_port} 失败: {e}")

    def disconnect(self) -> None:
        """断开与雷达设备的连接"""
        self._stop_receiving = True
        self.is_connected = False

        if self._receive_thread and self._receive_thread.is_alive():
            self._receive_thread.join(timeout=2)

        if self.data_socket:
            self.data_socket.close()
            self.data_socket = None

        if self.control_socket:
            self.control_socket.close()
            self.control_socket = None

    def send_data(self, data: bytes) -> None:
        """发送数据到雷达设备"""
        if not self.is_connected or not self.data_socket:
            raise RadarConnectionError("未连接到雷达设备")

        try:
            self.data_socket.sendall(data)
        except socket.error as e:
            raise RadarConnectionError(f"发送数据失败: {e}")

    def receive_data(self, timeout: Optional[int] = None) -> bytes:
        """从雷达设备接收数据"""
        if not self.is_connected or not self.data_socket:
            raise RadarConnectionError("未连接到雷达设备")

        try:
            old_timeout = self.data_socket.gettimeout()
            if timeout is not None:
                self.data_socket.settimeout(timeout / 1000)

            # 接收数据长度（假设前2字节是数据长度）
            length_data = self.data_socket.recv(2)
            if len(length_data) < 2:
                raise RadarTimeoutError("接收数据超时")

            data_length = int.from_bytes(length_data, byteorder='big')

            # 接收实际数据
            received_data = bytearray()
            remaining = data_length

            while remaining > 0:
                chunk = self.data_socket.recv(min(remaining, 4096))
                if not chunk:
                    raise RadarConnectionError("连接断开")
                received_data.extend(chunk)
                remaining -= len(chunk)

            return bytes(received_data)

        except socket.timeout:
            raise RadarTimeoutError("接收数据超时")
        finally:
            if timeout is not None:
                self.data_socket.settimeout(old_timeout)

    def send_command(self, command: bytes, timeout: Optional[int] = None) -> bytes:
        """发送命令并等待响应"""
        if not self.is_connected or not self.control_socket:
            raise RadarConnectionError("未连接到雷达设备")

        try:
            old_timeout = self.control_socket.gettimeout()
            if timeout is not None:
                self.control_socket.settimeout(timeout / 1000)

            # 发送命令
            self.control_socket.sendall(command)

            # 接收响应
            response = self.control_socket.recv(4096)
            return response

        except socket.timeout:
            raise RadarTimeoutError("命令响应超时")
        finally:
            if timeout is not None:
                self.control_socket.settimeout(old_timeout)

    def _start_receiving(self) -> None:
        """启动数据接收线程"""
        self._stop_receiving = False
        self._receive_thread = threading.Thread(target=self._receive_loop, daemon=True)
        self._receive_thread.start()

    def _receive_loop(self) -> None:
        """数据接收循环"""
        while not self._stop_receiving and self.is_connected:
            try:
                if self.data_socket:
                    # 设置短超时以便及时检查停止标志
                    self.data_socket.settimeout(0.1)
                    try:
                        data = self.receive_data()
                        self._handle_received_data(data)
                    except RadarTimeoutError:
                        continue
                    except Exception as e:
                        if not self._stop_receiving:
                            print(f"接收数据错误: {e}")
                        break
            except Exception as e:
                if not self._stop_receiving:
                    print(f"接收线程错误: {e}")
                break

    def get_connection_info(self) -> dict:
        """获取连接信息"""
        return {
            'interface': 'RJ45',
            'host': self.host,
            'data_port': self.data_port,
            'control_port': self.control_port,
            'is_connected': self.is_connected
        }